`timescale 1 ps/1 ps
/************************************************************\
 **  Copyright (c) 2022-2023 Gonsin, Inc.
 **  All Right Reserved.
 **  Author: http://www.anlogic.com/
 **  Description: tx_clk_en_gen
 **  Rev 1.0
\************************************************************/

module tx_clk_en_gen (
input reset_i,                   //tx_reset
input speed10_100_i,
input speed100_i,
input clk_i,                     //gtx_clk/tx_clk：  125MHz
output reg client_txcen_o,       //tx_clk_en
output reg gmii_txcen_o,
output reg rgmii_txcen_o,
output reg rgmii_txcen_shift_o
);
//----------------------------------------------------------------
//模块内部信号
reg [5:0] counter6b;
reg [5:0] divide6b_val;
reg [5:0] first6b_edge;
reg [5:0] second6b_edge;
reg client_txcen_int;

wire speed10_100_int_w;
wire speed100_int_w;

reg rgmii_txcen_int;
reg rgmii_txcen_shiftint;
 
//---------------------------------------------------------------- 
// 本地同步速度指示信号
sync_block speed_10_100_sync 
(
  .clk_i(clk_i),
  .data_i(speed10_100_i),
  .data_o(speed10_100_int_w)
);

sync_block speed_100_sync 
(
  .clk_i(clk_i),
  .data_i(speed100_i),
  .data_o(speed100_int_w)
);

//---------------------------------------------------------------- 
// 产生一个6位计数器，然后 自动计数值 取决于 速度设置
always@(posedge clk_i) begin
  if (reset_i) begin
    counter6b <= 0;
  end
  else begin
    if (counter6b >= divide6b_val) // 1Gbps时：divide_val = 0；counter = 0
      counter6b <= 0;
    else 
      counter6b <= counter6b + 1;
  end
end

always@(speed10_100_int_w or speed100_int_w) begin
  if (!speed10_100_int_w) begin // 1Gbps
    divide6b_val = 0;
    first6b_edge = 0;
    second6b_edge = 0;
  end
  else begin
    if (speed100_int_w) begin // 100Mbps
      divide6b_val = 4;  // 125MHz/5=25MHz 
      first6b_edge = 1;  
      second6b_edge = 2;
    end
    else begin // 10Mbps
      divide6b_val = 49; // 125MHz/50=2.5MHz 
      first6b_edge = 23;
      second6b_edge = 24;
    end
  end
end

//---------------------------------------------------------------- 
//生成 rgmii_txc时钟使能 信号(在rgmii_interface模块中输入给ODDR) - 仅在速度 10/100Mbps时（不为1Gbps）
always@(posedge clk_i) begin
  if (reset_i) begin
    rgmii_txcen_int <= 0;
    rgmii_txcen_shiftint <= 0;
  end
  else begin
    if (speed10_100_int_w) begin  // 10/100Mbps
      // 在rgmii_interface模块中输入给ODDR，100Mbps对应产生rgmii_txc=25MHz,10Mbps对应产生rgmii_txc=2.5MHz,
      if (counter6b >= divide6b_val) begin
        rgmii_txcen_int <= 1;
        rgmii_txcen_shiftint <= 1;
      end
      else if (counter6b == first6b_edge) begin  //rgmii_txc_en_shift_int高电平持续时间比rgmii_txc_en_int多一拍
        rgmii_txcen_int <= 0;
        rgmii_txcen_shiftint <= 1;
      end
      else if (counter6b == second6b_edge) begin
        rgmii_txcen_int <= 0;
        rgmii_txcen_shiftint <= 0;
      end
    end
    else begin  // 1Gbps
      // 在rgmii_interface模块中输入给ODDR，产生rgmii_txc=125MHz
      rgmii_txcen_int <= 0;
      rgmii_txcen_shiftint <= 1;
    end
  end
end     

//---------------------------------------------------------------- 
//需要控制使能和时钟之间的流水线延迟，以确保IO的正确时序
always@(posedge clk_i) begin
  if (reset_i) begin
    rgmii_txcen_o <= 0;
    rgmii_txcen_shift_o <= 0;
  end
  else begin
    rgmii_txcen_o <= rgmii_txcen_int;
    rgmii_txcen_shift_o <= rgmii_txcen_shiftint;
  end
end

//---------------------------------------------------------------- 
// client_txc时钟使能-我们要每隔一个脉冲生成第二个使能
always@(posedge clk_i) begin
  if(reset_i) begin
    client_txcen_int <= 0;
  end
  else begin
    if (speed10_100_int_w) begin // 10/100Mbps
      if (counter6b >= divide6b_val) begin
        client_txcen_int <= !client_txcen_int; //100Mbps对应产生 client_txc=12.5MHz,10Mbps对应产生 client_txc =1.25MHz
      end
    end
    else begin
      client_txcen_int <= 0;
    end
  end
end

//---------------------------------------------------------------- 
//需要控制MAC使能和时钟之间的流水线延迟，以确保IO的正确时序：  gmii_txc_en高电平比 rgmii_txc_en高电平 早一个时钟周期

always@(posedge clk_i) begin
  if(reset_i) begin
    client_txcen_o <= 0;
    gmii_txcen_o <= 0;
  end
  else begin
    if (counter6b >= divide6b_val) begin  //100Mbps对应产生 gmii_txcen_o=25MHz,10Mbps对应产生 gmii_txcen_o =2.5MHz
      gmii_txcen_o <= 1;  // gmii_txcen_o 一个周期（8ns）高电平
    end  // 1Gbps时：divide_val = 0；counter = 0; 对应产生 gmii_txcen_o = 1; 对应产生 gmii_tx_clk = 125MHz
    else begin  
      gmii_txcen_o           <= 0;
    end

    if ((counter6b >= divide6b_val) & !client_txcen_int) begin //100Mbps对应产生 client_txc=12.5MHz,10Mbps对应产生 client_txc =1.25MHz
      client_txcen_o <= 1; //  一个周期（8ns）高电平
    end   // 1Gbps时：divide_val = 0；counter = 0; 对应产生 client_txcen_o = 1;  对应产生client_txc =125MHz
    else begin
      client_txcen_o <= 0;
    end
  end
end

endmodule